# 智能学习桌项目 Makefile
# 用于编译EBP3901平台的C代码

# 工具链配置
TOOLCHAIN_PREFIX = arm-none-eabi-
CC = $(TOOLCHAIN_PREFIX)gcc
AS = $(TOOLCHAIN_PREFIX)as
LD = $(TOOLCHAIN_PREFIX)ld
OBJCOPY = $(TOOLCHAIN_PREFIX)objcopy
OBJDUMP = $(TOOLCHAIN_PREFIX)objdump
SIZE = $(TOOLCHAIN_PREFIX)size
GDB = $(TOOLCHAIN_PREFIX)gdb

# 目标配置
TARGET = smart_desk
PLATFORM = EBP3901

# 目录配置
SRC_DIR = .
BUILD_DIR = build
MAIN_DIR = 主系统集成
HAL_DIR = 硬件适配层
VOICE_DIR = 模块一_智能语音交互系统
POSTURE_DIR = 模块二_超声波坐姿监测系统

# 源文件
C_SOURCES = \
	$(MAIN_DIR)/main.c \
	$(HAL_DIR)/ebp3901_drivers.c \
	$(VOICE_DIR)/voice_interaction.c

# 头文件路径
INCLUDES = \
	-I$(HAL_DIR) \
	-I$(VOICE_DIR) \
	-I$(POSTURE_DIR)

# 编译器标志
CFLAGS = \
	-mcpu=cortex-m4 \
	-mthumb \
	-mfpu=fpv4-sp-d16 \
	-mfloat-abi=hard \
	-Wall \
	-Wextra \
	-Wno-unused-parameter \
	-std=c99 \
	-ffunction-sections \
	-fdata-sections \
	-g \
	-O2

# 预处理器定义
DEFINES = \
	-DPLATFORM_EBP3901=1 \
	-DCPU_FREQUENCY_MHZ=168 \
	-DDEBUG_ENABLE=1

# 链接器标志
LDFLAGS = \
	-mcpu=cortex-m4 \
	-mthumb \
	-mfpu=fpv4-sp-d16 \
	-mfloat-abi=hard \
	-specs=nano.specs \
	-specs=nosys.specs \
	-Wl,--gc-sections \
	-Wl,-Map=$(BUILD_DIR)/$(TARGET).map \
	-Wl,--print-memory-usage

# 链接脚本
LDSCRIPT = $(HAL_DIR)/linker_script.ld

# 对象文件
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))

# 默认目标
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin size

# 创建构建目录
$(BUILD_DIR):
	mkdir -p $(BUILD_DIR)

# 编译C文件
$(BUILD_DIR)/%.o: $(MAIN_DIR)/%.c | $(BUILD_DIR)
	@echo "编译 $<"
	$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@

$(BUILD_DIR)/%.o: $(HAL_DIR)/%.c | $(BUILD_DIR)
	@echo "编译 $<"
	$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@

$(BUILD_DIR)/%.o: $(VOICE_DIR)/%.c | $(BUILD_DIR)
	@echo "编译 $<"
	$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@

$(BUILD_DIR)/%.o: $(POSTURE_DIR)/%.c | $(BUILD_DIR)
	@echo "编译 $<"
	$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@

# 链接生成ELF文件
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(LDSCRIPT)
	@echo "链接 $@"
	$(CC) $(OBJECTS) $(LDFLAGS) -T$(LDSCRIPT) -o $@

# 生成HEX文件
$(BUILD_DIR)/$(TARGET).hex: $(BUILD_DIR)/$(TARGET).elf
	@echo "生成 $@"
	$(OBJCOPY) -O ihex $< $@

# 生成BIN文件
$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf
	@echo "生成 $@"
	$(OBJCOPY) -O binary $< $@

# 显示大小信息
size: $(BUILD_DIR)/$(TARGET).elf
	@echo "内存使用情况:"
	$(SIZE) $<

# 生成反汇编文件
disasm: $(BUILD_DIR)/$(TARGET).elf
	@echo "生成反汇编文件"
	$(OBJDUMP) -d $< > $(BUILD_DIR)/$(TARGET).dis

# 调试版本
debug: CFLAGS += -DDEBUG=1 -g3 -O0
debug: all

# 发布版本
release: CFLAGS += -DNDEBUG -O2
release: all

# 烧录程序
flash: $(BUILD_DIR)/$(TARGET).hex
	@echo "烧录程序到EBP3901..."
	openocd -f interface/stlink.cfg -f target/stm32f4x.cfg \
		-c "program $(BUILD_DIR)/$(TARGET).hex verify reset exit"

# 使用J-Link烧录
flash-jlink: $(BUILD_DIR)/$(TARGET).hex
	@echo "使用J-Link烧录程序..."
	JLinkExe -device STM32F407VG -if SWD -speed 4000 \
		-CommanderScript flash_script.jlink

# 启动调试会话
debug-openocd: $(BUILD_DIR)/$(TARGET).elf
	@echo "启动OpenOCD调试会话..."
	openocd -f interface/stlink.cfg -f target/stm32f4x.cfg &
	$(GDB) $< -ex "target remote localhost:3333"

# 启动J-Link调试会话
debug-jlink: $(BUILD_DIR)/$(TARGET).elf
	@echo "启动J-Link调试会话..."
	JLinkGDBServer -device STM32F407VG -if SWD -speed 4000 &
	$(GDB) $< -ex "target remote localhost:2331"

# 清理构建文件
clean:
	@echo "清理构建文件..."
	rm -rf $(BUILD_DIR)

# 完全清理
distclean: clean
	@echo "完全清理..."
	rm -f *.log *.tmp

# 检查工具链
check-toolchain:
	@echo "检查工具链..."
	@which $(CC) > /dev/null || (echo "错误: $(CC) 未找到" && exit 1)
	@which $(OBJCOPY) > /dev/null || (echo "错误: $(OBJCOPY) 未找到" && exit 1)
	@which $(SIZE) > /dev/null || (echo "错误: $(SIZE) 未找到" && exit 1)
	@echo "工具链检查通过"
	@$(CC) --version

# 代码格式化
format:
	@echo "格式化代码..."
	find $(SRC_DIR) -name "*.c" -o -name "*.h" | xargs clang-format -i

# 静态分析
analyze:
	@echo "执行静态分析..."
	cppcheck --enable=all --std=c99 $(C_SOURCES)

# 生成文档
docs:
	@echo "生成文档..."
	doxygen Doxyfile

# 运行单元测试
test:
	@echo "运行单元测试..."
	# 这里可以添加单元测试命令

# 创建发布包
package: release
	@echo "创建发布包..."
	mkdir -p release
	cp $(BUILD_DIR)/$(TARGET).hex release/
	cp $(BUILD_DIR)/$(TARGET).bin release/
	cp $(BUILD_DIR)/$(TARGET).elf release/
	cp README.md release/
	tar -czf release/$(TARGET)_$(shell date +%Y%m%d).tar.gz release/

# 显示帮助信息
help:
	@echo "智能学习桌项目构建系统"
	@echo ""
	@echo "可用目标:"
	@echo "  all          - 编译所有文件 (默认)"
	@echo "  debug        - 编译调试版本"
	@echo "  release      - 编译发布版本"
	@echo "  clean        - 清理构建文件"
	@echo "  distclean    - 完全清理"
	@echo "  size         - 显示内存使用情况"
	@echo "  disasm       - 生成反汇编文件"
	@echo "  flash        - 烧录程序 (OpenOCD)"
	@echo "  flash-jlink  - 烧录程序 (J-Link)"
	@echo "  debug-openocd- 启动OpenOCD调试"
	@echo "  debug-jlink  - 启动J-Link调试"
	@echo "  check-toolchain - 检查工具链"
	@echo "  format       - 格式化代码"
	@echo "  analyze      - 静态分析"
	@echo "  docs         - 生成文档"
	@echo "  test         - 运行测试"
	@echo "  package      - 创建发布包"
	@echo "  help         - 显示此帮助信息"
	@echo ""
	@echo "示例:"
	@echo "  make all           # 编译项目"
	@echo "  make debug         # 编译调试版本"
	@echo "  make flash         # 烧录到开发板"
	@echo "  make clean         # 清理构建文件"

# 伪目标
.PHONY: all debug release clean distclean size disasm flash flash-jlink \
        debug-openocd debug-jlink check-toolchain format analyze docs \
        test package help

# 依赖关系
$(BUILD_DIR)/main.o: $(HAL_DIR)/hardware_abstraction.h $(HAL_DIR)/system_config.h
$(BUILD_DIR)/ebp3901_drivers.o: $(HAL_DIR)/hardware_abstraction.h $(HAL_DIR)/system_config.h
$(BUILD_DIR)/voice_interaction.o: $(HAL_DIR)/hardware_abstraction.h $(HAL_DIR)/system_config.h